package cn.yj.wx.pay.wrapper;

import cn.yj.common.emums.PayFrom;
import cn.yj.common.emums.PayType;
import cn.yj.common.entity.*;
import cn.yj.common.interfaces.IPayFromExecutor;
import cn.yj.commons.utils.StringUtils;
import cn.yj.tools.exception.ServiceException;
import cn.yj.wx.pay.enrity.AppPayOrderResult;
import cn.yj.wx.pay.enrity.JSAPIPayOrderResult;
import cn.yj.wx.pay.enrity.PayOrderResult;
import cn.yj.wx.pay.enrity.WechatPayRequest;
import cn.yj.common.exception.PayException;
import cn.yj.wx.pay.enrity.refund.RefundRequest;
import cn.yj.wx.pay.enrity.refund.WechatRefundResult;
import cn.yj.wx.pay.service.handler.AbstractWxPay;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 永健
 * @since 2021-09-23 09:39
 */
public class WechatPayExecutor implements ApplicationContextAware, IPayFromExecutor<AliPayResult, WechatPayRequest> {
    private static ApplicationContext app;

    public static WechatPayExecutor getInstance() {
        if (app == null) {
            throw new ServiceException("未启用微信支付");
        }
        return app.getBean(WechatPayExecutor.class);
    }

    @Resource
    private List<AbstractWxPay> aliPays;


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        app = applicationContext;
    }

    public JSAPIPayOrderResult underOrderObject(PayFrom from, WechatPayRequest request) throws PayException{
        for (AbstractWxPay aliPay : aliPays) {
            if (aliPay.support(from)) {
                return (JSAPIPayOrderResult) aliPay.underOrder(request);
            }
        }
        throw new ServiceException("找不到适配该支付的处理器");
    }


    @Override
    public AliPayResult underOrder(PayFrom from, WechatPayRequest request) throws PayException {
        AliPayResult aliPayResult = new AliPayResult();
        aliPayResult.setSuccess(true);
        Map<String, Object> body = new HashMap<>();
        for (AbstractWxPay aliPay : aliPays) {
            if (aliPay.support(from)) {
                PayOrderResult payOrderResult = (PayOrderResult) aliPay.underOrder(request);
                aliPayResult.setCode(payOrderResult.getCode());
                aliPayResult.setMsg(payOrderResult.getMessage());
                body.put("body", payOrderResult.getResult());
                aliPayResult.setBody(body);
                aliPayResult.setOutTradeNo(payOrderResult.getOutTradeNo());
                aliPayResult.setTotalAmount(payOrderResult.getTotalAmount());
                if (from == PayFrom.APP) {
                    AppPayOrderResult orderResult = (AppPayOrderResult) payOrderResult;
                    aliPayResult.setBody(JSON.parseObject(JSON.toJSONString(orderResult), Map.class));
                } else if (from == PayFrom.JSAPI) {
                    JSAPIPayOrderResult orderResult = (JSAPIPayOrderResult) payOrderResult;
                    aliPayResult.setBody(JSON.parseObject(JSON.toJSONString(orderResult), Map.class));
                }
                return aliPayResult;
            }
        }
        throw new ServiceException("找不到适配该支付的处理器");
    }

    @Override
    public WechatRefundResult refund(RefundParams refundParams) throws PayException {
        AbstractWxPay abstractWxPay = aliPays.get(0);
        if (StringUtils.isNull(refundParams)) {
            throw new ServiceException("缺少申请退款参数对象 RefundParams.class");
        }
        String out_trade_no = refundParams.getOutTradeNo();
        String refund_no = refundParams.getOutRefundNo();
        BigDecimal refundAmount = refundParams.getRefundAmount();
        BigDecimal sourceAmount = refundParams.getSourceAmount();
        RefundRequest rq = new RefundRequest();

        RefundRequest.Amount amount = new RefundRequest.Amount();
        double v = refundAmount.doubleValue() * 100;
        double v1 = sourceAmount.doubleValue()*100;
        amount.setRefund(new BigDecimal(v).intValue());
        amount.setTotal(new BigDecimal(v1).intValue());

        rq.setAmount(amount);
        rq.setOut_refund_no(refund_no);
        rq.setOut_trade_no(out_trade_no);
        return abstractWxPay.refund(rq);
    }


    @Override
    public WechatPayRequest getRequestParams(PayFrom from, Map<String, Object> params) {
        Gson gson = new Gson();
        return gson.fromJson(JSONObject.toJSONString(params), WechatPayRequest.class);
    }

    @Override
    public PayRefundOrder queryRefundOrder(RefundQueryParams params) throws PayException {
        AbstractWxPay abstractWxPay = aliPays.get(0);
        return abstractWxPay.queryRefundOrder(params);
    }

    @Override
    public PayOrder queryOrder(String outTradeNo) {
        AbstractWxPay abstractWxPay = aliPays.get(0);
        return abstractWxPay.queryOrder(outTradeNo);
    }
}
